#ifndef HELPER_H
#define HELPER_H
#pragma warning(disable:4996)

#include <string>
#include <vector>
#include <fstream>
#include <cassert>
#include <map>
#include <boost/serialization/access.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/map.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

using namespace std;
class FileHelper {
	friend boost::serialization::access;
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		ar & fileInfo;
		ar & indexInfo;
	}
public :
	map<string, pair<unsigned int, unsigned int> > fileInfo;
	map<unsigned int, string> indexInfo;
	void BuildPosition() {
		map<string, pair<unsigned int, unsigned int> >::iterator it;
		for (it = fileInfo.begin(); it != fileInfo.end(); it++) {
			indexInfo[it->second.first] = it->first;
		}
	}

	string GetFileName(unsigned int index) {
		map<unsigned int, string>::iterator it;
		it = indexInfo.find(index);
		if (it != indexInfo.end()) {
			return it->second;
		}
		it = indexInfo.lower_bound(index);
		it --;
		return it->second;
	}

	void AddFileName(string key, unsigned int count) {
		map<string, pair<unsigned int, unsigned int> >::iterator it;
		if ((it = fileInfo.find(key)) != fileInfo.end()) {
			it->second.second += 1;
		} else {
			pair<unsigned int, unsigned int> p(count, 1);
			fileInfo[key] = p;
		}
	}

	pair<unsigned int, unsigned int> GetRecordNum(string filename) {
		map<string, pair<unsigned int, unsigned int> >::iterator it;
		it = fileInfo.find(filename);
		if (it != fileInfo.end()) {
			return it->second;
		} else {
			throw exception("Illegal file name.");
		}
	}
};

void SaveFileHelper(FileHelper * ifh, const string & filename) {
	ofstream ofs(filename.c_str(), ios::binary);
	assert(ofs.good());
	boost::archive::binary_oarchive oa(ofs);
	oa << *ifh;
	ofs.close();
}

void LoadFileHelper(FileHelper * ifh, const string & filename) {
	ifstream ifs(filename.c_str(), ios::binary);
	assert(ifs.good());
	boost::archive::binary_iarchive ia(ifs);
	ia >> *ifh;
	ifs.close();
}

#endif